Skip to content

Vcu mode set over can#307

Open
cyberneel wants to merge 5 commits into
mainfrom
vcu-mode-set-can
Open

Vcu mode set over can#307
cyberneel wants to merge 5 commits into
mainfrom
vcu-mode-set-can

Conversation

@cyberneel

Copy link
Copy Markdown
Collaborator

Added CAN from BEVO to tell VCU what mode we want it and updated trackside front end to allow runtime changes.

New Pi->VCU CAN packet so the VCU's params table (acceleration/skidpad/
autocross/endurance) can be selected at runtime over CAN instead of the
compile-time SELECTED_PARAMS #define. 8 bytes for extensibility; byte0 =
event_mode (1=accel 2=skid 3=autox 4=endur), bytes 1-7 reserved.

Regenerated C drivers (can_ids.h/.c) give the VCU VCU_MODE_COMMAND_ID,
msg_vcu_mode_command_t{event_mode}, and unpack_vcu_mode_command() to wire a
receive handler against. Command packet => no telemetry/proto/SQL changes.
Regen chain: update_can_proto.py + sync_assets.sh + sync_schema.sh +
generate_can_lib.py (CI schema-drift chain + the VCU C-driver gen).
cand: add a single-writer CAN transmit thread on can0 (critical bus, where the
VCU listens). It owns the only write socket and serves /tmp/BEVO_cand_tx.sock;
clients send 13-byte frame requests (u32 LE id, u8 dlc, 8 data bytes). Keeps
cand the sole CAN writer.

dashd: on lhre/dash/eventMode, relay the value to cand as the 0x029 VCU Mode
Command frame (byte0=event_mode) and ack on lhre/dash/ack/eventMode. dashd
doesn't interpret the mode; the VCU re-broadcasts event_mode in 0x1C7 which
trackside already reads back as confirmation.
dashSignals.publishEventMode(mode) publishes lhre/dash/eventMode (qos 1); a new
'VCU Mode' panel on the Dash tab lets the strategist pick Acceleration/Skidpad/
Autocross/Endurance and send it. dashd relays it onto CAN as 0x029, the VCU
applies + re-broadcasts its mode, closing the loop with the existing MODE read.
@cyberneel cyberneel requested review from a team as code owners June 13, 2026 03:22
@cyberneel cyberneel requested review from Anish-Y, KaitlynWChang, celinayang13 and zohaib642 and removed request for a team June 13, 2026 03:22
@vercel

vercel Bot commented Jun 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lhre-2026 Ready Ready Preview, Comment Jun 15, 2026 6:20am

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a single-writer CAN transmit path to allow trackside VCU mode commands (0x029) to be relayed from MQTT to the critical CAN bus via dashd and cand. It also updates the telemetry frontend to provide a UI panel for selecting and sending these modes. The review comments point out two important issues: a potential truncation bug in cand when casting CAN IDs to u16 without validating standard bounds, and unsafe parsing of localStorage values in the frontend without validating against allowed VCU modes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread BEVO/cand/main.rs Outdated
Comment on lines +376 to +382
let sid = match StandardId::new(id as u16) {
Some(s) => s,
None => {
eprintln!("[CAND-TX] rejecting non-standard CAN id {:#x}", id);
continue;
}
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Casting id as u16 directly can lead to silent truncation bugs if the client sends an ID greater than 0xFFFF or an extended CAN ID (which are 29-bit). For example, 0x10005 would be truncated to 5, which is a valid standard ID, and thus sent incorrectly. We should explicitly check that id is within the valid standard CAN ID range (<= 0x7FF) before attempting to construct the StandardId.

            let sid = if id <= 0x7FF {
                StandardId::new(id as u16)
            } else {
                None
            };
            let sid = match sid {
                Some(s) => s,
                None => {
                    eprintln!("[CAND-TX] rejecting non-standard CAN id {:#x}", id);
                    continue;
                }
            };

const [dashPowerMode, setDashPowerMode] = useState<"auto" | "manual">(() => (localStorage.getItem("dash-power-mode") === "manual" ? "manual" : "auto"));
const [dashAutoLap, setDashAutoLap] = useState(() => localStorage.getItem("dash-auto-lap") === "1");
// Selected VCU params table to command (event_mode); persisted for convenience.
const [vcuMode, setVcuMode] = useState<number>(() => Number(localStorage.getItem("dash-vcu-mode") || 4));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Parsing localStorage values directly using Number(...) can be unsafe if the stored value is corrupted, empty, or not a valid mode number (e.g., resulting in NaN or an out-of-bounds value like 0 or 5). It is safer to parse the value and validate that it is one of the allowed VCU modes (1, 2, 3, or 4), defaulting to 4 (Endurance) if invalid.

  const [vcuMode, setVcuMode] = useState<number>(() => {
    const saved = localStorage.getItem("dash-vcu-mode");
    const parsed = saved ? Number(saved) : 4;
    return [1, 2, 3, 4].includes(parsed) ? parsed : 4;
  });

@cyberneel

Copy link
Copy Markdown
Collaborator Author

@matt-mekha Add your VCU side code to this branch.

I also updated the schema assets which seemed to have picked up HVC stuff so those are also shown as additions in this PR.

- cand: range-check id <= 0x7FF before 'id as u16' so an extended/>16-bit id
  (e.g. 0x10005) can't silently truncate (-> 0x5) and transmit to the wrong
  node (Gemini, high).
- trackside: validate the localStorage vcuMode is one of 1-4, else default 4,
  so a corrupted/empty value can't preselect an invalid mode (Gemini, medium).
@matt-mekha matt-mekha requested a review from a team as a code owner June 15, 2026 06:19
@matt-mekha matt-mekha requested review from samuelLi05 and removed request for a team June 15, 2026 06:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant